package org.zoomdev.zoom.common.caster;

import org.apache.commons.lang3.StringUtils;
import org.zoomdev.zoom.common.utils.Classes;

import java.lang.reflect.Array;
import java.lang.reflect.Method;

class Enums {
    public static Emu2Int emu2Int = new Emu2Int();

    static class FromEmuProvider extends CasterProviderWithClass {
        @Override
        public ValueCaster getCaster(Class<?> srcType, Class<?> toType) {
            if (srcType.isEnum()) {
                if (CharSequence.class.isAssignableFrom(toType)) {
                    return Object2String.CASTER;
                }
                if (toType == int.class || toType == Integer.class) {
                    return emu2Int;
                }

                if (Number.class.isAssignableFrom(toType)) {
                    return new CasterBridge(emu2Int, Integer.class, toType);
                }
                //number
                if (Caster.isNumber(toType)) {
                    return new CasterBridge(emu2Int, Integer.class, toType);
                }
            }
            return null;
        }
    }

    static class ToEnumProvider extends CasterProviderWithClass {
        @Override
        public ValueCaster getCaster(Class<?> srcType, Class<?> toType) {
            if (toType.isEnum()) {
                if (CharSequence.class.isAssignableFrom(srcType)) {
                    try {
                        Method method = toType.getMethod("valueOf", String.class);
                        return new String2Enum(method, toType);
                    } catch (NoSuchMethodException e) {
                        throw new CasterException("不能将String转化为enum " + toType + " 找不到valueOf方法");
                    }
                }

                if (srcType == int.class || srcType == Integer.class) {
                    try {
                        Method method = toType.getMethod("values");
                        Object values = method.invoke(null);
                        return new Int2Emu(values);
                    } catch (Exception e) {
                        throw new CasterException("不能将String转化为enum " + toType + " 找不到valueOf方法");
                    }
                }

                if (Classes.isInteger(srcType)) {
                    return new CasterBridge(srcType, Integer.class, toType);
                }

            }
            return null;
        }

    }

    static class Emu2Int implements ValueCaster {

        @Override
        public Object to(Object src) {
            return ((Enum) src).ordinal();
        }
    }

    static class Int2Emu implements ValueCaster {

        private final Object anEnum;

        public Int2Emu(Object anEnum) {
            this.anEnum = anEnum;
        }

        @Override
        public Object to(Object src) {
            Integer index = (Integer) src;
            return Array.get(anEnum, index);
        }
    }

    static class String2Enum implements ValueCaster {

        private final Method method;

        private final Class<?> type;

        public String2Enum(Method method, Class<?> type) {
            this.method = method;
            this.type = type;
        }

        @Override
        public Object to(Object src) {
            try {
                if (StringUtils.isEmpty((String) src)) {
                    return null;
                }
                return method.invoke(null, src);
            } catch (Exception e) {
                throw new CasterException("类型转化异常,字符串:" + src + "不能转化为" + type, Classes.getCause(e));
            }
        }
    }
}
